package tech.fangsong.client.handler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import tech.fangsong.im.core.protocol.ImMsg;

import java.util.List;

/**
 * 编解码
 */
public class ImCodecHandler extends MessageToMessageCodec<ByteBuf, ImMsg> {

    @Override
    protected void encode(ChannelHandlerContext ctx, ImMsg imMsg, List<Object> list) throws Exception {
        ByteBuf byteBuf = ctx.alloc().ioBuffer();
        byteBuf.writeByte(ImMsg.getHeaderMagic());
        byteBuf.writeShort(imMsg.getVersion());
        byteBuf.writeByte(imMsg.getFamily());
        byteBuf.writeByte(imMsg.getCmd());
        byteBuf.writeByte(imMsg.getType());
        byteBuf.writeLong(imMsg.getSequence());
        byteBuf.writeInt(imMsg.getPayloadLength());
        byteBuf.writeBytes(imMsg.getPayload());
        list.add(byteBuf);
    }

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        // 可读字节是否大于包头长度
        if(byteBuf.readableBytes() < ImMsg.getHeaderLength()){
            // 等待完整数据包
            return;
        }

        // 跳过不需要读取的字节码
        /*if(byteBuf.readableBytes() > MAX_DATA_LENGTH){
            byteBuf.skipBytes(byteBuf.readableBytes());
        }*/

        int beginReader;
        while (true){
            // 获取包头开始的index
            beginReader = byteBuf.readerIndex();
            // 标记包头开始的index
            byteBuf.markReaderIndex();

            if(byteBuf.readByte() == ImMsg.getHeaderMagic()){
                break;
            }

            // 到这里表明没有读取到包头标识，继续往后读取一个字节
            byteBuf.resetReaderIndex();
            byteBuf.readByte();

            // 等待完整数据包
            if(byteBuf.readableBytes() < ImMsg.getHeaderLength()){
                return;
            }
        }

        // 到表明读取到了头标识magic，需要读取头其他数据
        short version = byteBuf.readShort();
        byte family = byteBuf.readByte();
        byte cmd = byteBuf.readByte();
        byte type = byteBuf.readByte();
        long sequence = byteBuf.readLong();
        int payloadLength = byteBuf.readInt();

        if(byteBuf.readableBytes() < payloadLength){
            // 表明 body还未读取完，还原读指针
            byteBuf.readerIndex(beginReader);
            return;
        }

        byte[] bodyData = new byte[payloadLength];
        byteBuf.readBytes(bodyData);

        ImMsg imMsg = new ImMsg();
        imMsg.setFamily(family);
        imMsg.setCmd(cmd);
        imMsg.setType(type);
        imMsg.setVersion(version);
        imMsg.setSequence(sequence);
        imMsg.setPayloadLength(payloadLength);
        imMsg.setPayload(bodyData);
        list.add(imMsg);
    }
}
